﻿using UnityEngine;
using System;
using FrameWorkSong;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using System.Linq;
using UnityStandardAssets.CinematicEffects;

public enum CameraState { Move, Static }
public class MouseControlCamera : Singleton<MouseControlCamera>
{
    public enum MoveMode { fly, first }
    enum RayType { Mouse, Camera }
    public Transform MoveTrans;//相机父物体
    public Texture2D ZoomView, PanView, OrbitView;
    public CameraState cameraState = CameraState.Static;
    public float ZoomSpeed = 10;
    public float MoveSpeedNum = 10;
    public float AngleSpeed = 360;
    public bool isCameraControl = true;
    public MoveMode MyMoveMode = MoveMode.fly;
    public float FristHigh = 1.8f;//第一人称高度
    public override void OnBeforeDestroy() { }
    //是否更新目标位置
    bool CurRayPoint = false;

    //目标位置
    private Vector3 rayHitPoint;
    public Vector3 RayHitPoint
    {
        get
        {
            if (CurRayPoint)
            {

                Ray ray = new Ray(MoveTrans.position, MoveTrans.forward);
                RaycastHit hit;
                if (Physics.Raycast(ray, out hit))
                {
                    rayHitPoint = hit.point;

                }
                else
                {
                    //求目标物体pian在平面法线上的投影
                    float YN = Vector3.Dot(Vector3.down, MoveTrans.forward);
                    //计算缩放比例
                    float ratio = (MoveTrans.position.y) / YN;
                    rayHitPoint = (MoveTrans.forward * ratio) + MoveTrans.position;

                }
            }
            //  Debug.Log(rayHitPoint);
            return rayHitPoint;

        }
        set => rayHitPoint = value;
    }
    //相机到目标的距离
    private float ftCamerDis;
    public float FtCamerDis
    {
        get
        {
            ftCamerDis = Vector3.Distance(MoveTrans.position, RayHitPoint);
            return ftCamerDis;
        }
        set => ftCamerDis = value;
    }


    void Start()
    {
        cameraState = CameraState.Static;
    }

    void LateUpdate()
    {
        if (isCameraControl)
        {
            switch (MyMoveMode)
            {
                case MoveMode.fly:
                    flyMode();
                    break;
                case MoveMode.first:
                    firstMode();
                    break;
                default:
                    break;
            }
        }
    }
    void firstMode()
    {
        KeyTranslationForFirst();
        if (Input.GetMouseButton(1))
        {
            Rotate();
        }

    }
    void flyMode()
    {
        if (Input.GetMouseButtonUp(1) || Input.GetMouseButtonUp(0) || Input.GetMouseButtonUp(2) || Input.GetAxis("Mouse ScrollWheel") == 0)
        {
            SetMouseCursor();
            cameraState = CameraState.Static;
        }

        if (Input.GetMouseButton(0))
        {
            SetMouseCursor(PanView);
            Translation();
            cameraState = CameraState.Move;
        }
        if (Input.GetMouseButton(1))
        {
            SetMouseCursor(OrbitView);
            RotatePoint();
            cameraState = CameraState.Move;
        }
        if (Input.GetAxis("Mouse ScrollWheel") < 0)
        {
            SetMouseCursor(ZoomView);
            FrontMove(-1);
            cameraState = CameraState.Move;
        }
        if (Input.GetAxis("Mouse ScrollWheel") > 0)
        {

            SetMouseCursor(ZoomView);
            //   RayPoint(RayType.Camera);
            FrontMove(1);
            cameraState = CameraState.Move;
        }
        if (Input.GetKey(KeyCode.Q))
        {
            keyUpDown(1);
        }
        if (Input.GetKey(KeyCode.E))
        {
            keyUpDown(-1);
        }
        KeyTranslation();
    }
    void Update()
    {
        //按F10查看FPS
        if (Input.GetKeyDown(KeyCode.F10))
        {
            if (isLookFps == false)
            {
                isLookFps = true;
            }
            else
            {
                isLookFps = false;
            }
        }
        if (isLookFps)
        {
            CurLookFPS();
        }

    }

    #region 光标设置
    /// <summary>
    /// 设置光标
    /// </summary>
    /// <param name="mouseCursor"></param>
    void SetMouseCursor(Texture2D mouseCursor = null)
    {
        if (mouseCursor != null)
        {
            Cursor.SetCursor(mouseCursor, Vector2.zero, CursorMode.Auto);
        }
        else
        {
            Cursor.SetCursor(null, Vector2.zero, CursorMode.Auto);
        }
    }
    #endregion

    #region 鼠标控制
    Vector3 VecOffet = Vector3.zero;
    /// <summary>
    /// 平移控制
    /// </summary>
    /// <param name="sheep"></param>
    void Translation()
    {
        CurRayPoint = true;
        float moveX = -Input.GetAxis("Mouse X");
        float moveY = -Input.GetAxis("Mouse Y");
        Vector3 vec = Camera.main.transform.forward;
        Vector3 forward = new Vector3(vec.x, 0, vec.z).normalized;
        Vector3 vec1 = transform.right;
        Vector3 right = new Vector3(vec1.x, 0, vec1.z).normalized;
        MoveTrans.Translate((forward * moveY + right * moveX) * FtCamerDis * Time.deltaTime * MoveSpeedNum, Space.World);

    }
    void Rotate()
    {
        Vector3 eulerAngles = Camera.main.transform.eulerAngles;
        float eulerAngles_x = eulerAngles.y;
        float eulerAngles_y = eulerAngles.x;
        eulerAngles_x += (Input.GetAxis("Mouse X")) * Time.deltaTime * AngleSpeed * 2;
        eulerAngles_y -= (Input.GetAxis("Mouse Y")) * Time.deltaTime * AngleSpeed * 2;
        Quaternion quaternion = Quaternion.Euler(eulerAngles_y, eulerAngles_x, (float)0);
        MoveTrans.rotation = quaternion;
    }
    /// <summary>
    /// 绕点旋转
    /// </summary>
    void RotatePoint()
    {
        CurRayPoint = false;
        Vector3 eulerAngles = MoveTrans.eulerAngles;
        float eulerAngles_x = eulerAngles.y;
        float eulerAngles_y = eulerAngles.x;

        eulerAngles_x += (Input.GetAxis("Mouse X")) * Time.deltaTime * AngleSpeed;
        eulerAngles_y -= (Input.GetAxis("Mouse Y")) * Time.deltaTime * AngleSpeed;

        if (eulerAngles_y > 80)
        {
            eulerAngles_y = 80;
        }
        else if (eulerAngles_y < 23)
        {
            eulerAngles_y = 23;
        }
        Quaternion quaternion = Quaternion.Euler(eulerAngles_y, eulerAngles_x, (float)0);
        Vector3 vector = ((Vector3)(quaternion * new Vector3((float)0, (float)0, -FtCamerDis))) + RayHitPoint;

        MoveTrans.rotation = quaternion;
        MoveTrans.position = vector;

    }

    public void SetRayHitPoint(Vector3 vector)
    {
        RayHitPoint = vector;
    }
    /// <summary>
    /// 向前移动
    /// Direction[方向]
    /// </summary>
    /// <param name="intDirection">填写正反，1向前移动，2向后移动</param>
    void FrontMove(int intDirection)
    {
        CurRayPoint = false;
        if (ftCamerDis < 1)
        {
            ftCamerDis = 1;
        }
        MoveTrans.Translate(Vector3.forward * FtCamerDis * Time.deltaTime * ZoomSpeed * intDirection);
    }

    #endregion

    void readHigh()
    {
        Ray ray = new Ray(MoveTrans.position, -MoveTrans.up);
        float dis;
        RaycastHit hit;
        if (Physics.Raycast(ray, out hit))
        {
            dis = hit.point.y;
            //  Debug.Log(dis);
            Vector3 pos = MoveTrans.position;
            MoveTrans.position = new Vector3(pos.x, dis + FristHigh, pos.z);
        }

    }

    #region 键盘控制
    /// <summary>
    /// 键盘控制
    /// </summary>
    void KeyTranslation()
    {
        float moveX = Input.GetAxis("Horizontal") * Time.deltaTime * 10;
        float moveY = Input.GetAxis("Vertical") * Time.deltaTime * 10;
        if (moveX == 0 && moveY == 0)
        {
            return;
        }
        CurRayPoint = true;
        MoveTrans.Translate(new Vector3(moveX * 2, 0, moveY * 2) * FtCamerDis * Time.deltaTime * MoveSpeedNum, Space.Self);

    }
    void keyUpDown(int i)
    {
        if (MoveTrans.position.y >= 0.1f)
        {
            CurRayPoint = true;
            MoveTrans.Translate(new Vector3(0, i * 0.5f, 0) * FtCamerDis * Time.deltaTime * MoveSpeedNum, Space.Self);
        }
        else
        {
            Vector3 vec = MoveTrans.position;
            MoveTrans.position = new Vector3(vec.x, 0.1f, vec.z);
        }

    }
    void KeyTranslationForFirst()
    {
        float moveX = Input.GetAxis("Horizontal") * Time.deltaTime * 10;
        float moveY = Input.GetAxis("Vertical") * Time.deltaTime * 10;
        if (moveX == 0 && moveY == 0) return;
        readHigh();
        Vector3 vec = Camera.main.transform.forward;
        Vector3 forward = new Vector3(vec.x, 0, vec.z).normalized;
        Vector3 vec1 = transform.right;
        Vector3 right = new Vector3(vec1.x, 0, vec1.z).normalized;
        MoveTrans.Translate((forward * moveY + right * moveX) * Time.deltaTime * MoveSpeedNum, Space.World);
    }
    #endregion

    #region GetFps

    bool isLookFps = false;
    double lastInterval;
    int frames = 0;
    float fps;



    void CurLookFPS()
    {
        ++frames;
        float timeNow = Time.realtimeSinceStartup;
        if (timeNow > lastInterval + 0.5F)
        {
            fps = (float)(frames / (timeNow - lastInterval));
            frames = 0;
            lastInterval = timeNow;
        }
    }
    void OnGUI()
    {
        if (isLookFps)
        {
            GUILayout.Label("FPS:" + fps.ToString("f2"));
        }
        else
        {
            GUILayout.Label(" ");
        }
    }

    #endregion

    #region 控制API
    //计算一次目标点
    void GetRayPiont()
    {
        CurRayPoint = true;
        RayHitPoint = RayHitPoint;
    }
    public void FlyMode()
    {
        MyMoveMode = MoveMode.fly;
    }
    public void FirstMode(float high)
    {
        MyMoveMode = MoveMode.first;
        FristHigh = high;
    }
    public string GetCamerLoca()
    {
        JsonUtil.AddDataArray(MoveTrans.position.x.ToString());
        JsonUtil.AddDataArray(MoveTrans.position.y.ToString());
        JsonUtil.AddDataArray(MoveTrans.position.z.ToString());
        JsonUtil.AddDataArray(MoveTrans.eulerAngles.x.ToString());
        JsonUtil.AddDataArray(MoveTrans.eulerAngles.y.ToString());
        return JsonUtil.GetDataArray();
    }
    public void SetCamerLoca(float[] DataArray, float time)
    {
        if (MyMoveMode != MoveMode.fly) return;
        Vector3 newPosition = new Vector3(DataArray[0], DataArray[1], DataArray[2]);
        Vector3 newEulerAngle = new Vector3(DataArray[3], DataArray[4], 0);
        cameraState = CameraState.Move;
        DoMove(MoveTrans, newPosition, time);
        DoRotate(MoveTrans, newEulerAngle, time, () => { cameraState = CameraState.Static; });

    }
    //控制相机移动
    public void SetCamerLoca(float[] DataArray, float time, bool loop, Action next = null)
    {
        if (MyMoveMode != MoveMode.fly) return;
        StopSongTween("CameraMove");
        int count = DataArray.Length;

        List<Vector3> newPosition = new List<Vector3>();
        List<Vector3> newEulerAngle = new List<Vector3>();
        for (int i = 0; i < DataArray.Length; i += 5)
        {
            newPosition.Add(new Vector3(DataArray[i], DataArray[i + 1], DataArray[i + 2]));
            newEulerAngle.Add(new Vector3(DataArray[i + 3], DataArray[i + 4], 0));
        }
        cameraState = CameraState.Move;
        isCameraControl = false;
        if (newPosition.Count == 1 && MoveTrans.position == newPosition[0])
        {

        }
        else
        {
            DoMovePathWithRotate(MoveTrans, newPosition, newEulerAngle, time, loop, () =>
            {
                cameraState = CameraState.Static;
                isCameraControl = true;

                if (next != null)
                {
                    next();
                }
                GetRayPiont();
            }, "CameraMove");
        }


    }
    //控制相机移动（独立时间）
    public void SetCamerLocaForTime(float[] DataArray, bool loop)
    {
        if (MyMoveMode != MoveMode.fly) return;
        StopSongTween("CameraMove");
        int count = DataArray.Length;
        List<Vector3> newPosition = new List<Vector3>();
        List<Vector3> newEulerAngle = new List<Vector3>();
        List<float> newTime = new List<float>();
        for (int i = 0; i < DataArray.Length; i += 6)
        {
            newPosition.Add(new Vector3(DataArray[i], DataArray[i + 1], DataArray[i + 2]));
            newEulerAngle.Add(new Vector3(DataArray[i + 3], DataArray[i + 4], 0));
            newTime.Add(DataArray[i + 5]);
        }
        cameraState = CameraState.Move;
        isCameraControl = false;
        DoMovePathWithRotateForTime(MoveTrans, newPosition, newEulerAngle, newTime, loop, () =>
        {
            cameraState = CameraState.Static;
            isCameraControl = true;
            GetRayPiont();

        }, "CameraMove");
    }
    public void PauseCameraMove()
    {
        StopSongTween("CameraMove");
        isCameraControl = true;

    }
    public void StartCameraMove()
    {
        StartSongTween("CameraMove");
    }
    public void SetCamerMove(bool isMove)
    {
        isCameraControl = isMove;
    }
    public void CamerMoveForPos(float dis, float time)
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        if (Physics.Raycast(ray, out hit, 1 << LayerMask.NameToLayer("Pipe")))
        {
            SetRayHitPoint(hit.point);
            CamerMoveForPos(hit.point, dis, time);
        }
    }
    //相机移动到指定位置
    public void CamerMoveForPos(Vector3 pos, float dis, float time, Action action = null)
    {
        StopSongTween("CameraMove");
        Transform target = MoveTrans;
        Vector3 targetPos = pos - target.forward * dis;
        DoMove(target, targetPos, time, "CameraMove", () =>
        {
            if (action != null)
            {
                action();
            }
            RayHitPoint = pos;//将终点赋值给目标
        });
    }
    public void CamerMoveForPos(Vector3 pos, float time, Action action = null)
    {
        if (MyMoveMode != MoveMode.fly) return;
        StopSongTween("CameraMove");
        Transform target = MoveTrans;
        float dis = Vector3.Magnitude(target.position - pos);
        Vector3 targetPos = pos - target.forward * dis;
        DoMove(target, targetPos, time, "CameraMove", action);
        RayHitPoint = pos;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="pos"></param>
    /// <param name="dis"></param>
    /// <param name="time"></param>
    /// <param name="isRot"></param>
    /// <param name="overturn">是否翻转坐标</param>
    /// <param name="id"></param>
    /// <param name="action"></param>
    public void CamerMoveForPoss(Vector3[] pos, float dis, float time, bool isRot, bool overturn, Action action = null)
    {
        if (MyMoveMode != MoveMode.fly) return;
        StopSongTween("CameraMove");
        Transform target = MoveTrans;
        int length = pos.Length;
        List<Vector3> Atpos = new List<Vector3>(length);
        if (!overturn)
        {
            for (int i = 0; i < length; i++)
            {
                Atpos.Add(pos[i] - target.forward * dis);
            }
        }
        else
        {
            for (int i = length - 1; i >= 0; i--)
            {
                Atpos.Add(pos[i] - target.forward * dis);
            }
        }

        DoMovePath(target, Atpos, time, isRot, () =>
        {
            action();
        }, "CameraMove");
    }
    public void CamerMoveForObj(GameObject pos, float time, float rate)
    {
        if (MyMoveMode != MoveMode.fly) return;
        StopSongTween("CameraMove");
        Transform target = MoveTrans;
        Bounds bounds;
        Renderer renderer;
        pos.TryGetComponent<Renderer>(out renderer);
        bounds = renderer.bounds;
        Vector3 center = bounds.center;
        float dis = Vector3.Magnitude(bounds.size) * rate;
        Vector3 targetPos = center - target.forward * dis;
        DoMove(target, targetPos, time, "CameraMove", () =>
        {
            RayHitPoint = targetPos;
            PauseCameraMove();
        });
    }
}

#endregion


